package 课上练习0421_scala

import java.io.File
import scala.io.Source
import scala.language.implicitConversions

/**
 * 隐式转换
 */
class Scala_05_implicit extends App {
  val x = 3
  val y: Double = x // 低类型到高类型，隐式转换
  val z: Byte = x // 高类型到低类型，默认不支持转换（因为可能会有数据的损失），可以通过自定义隐式转换实现(int2Byte)

  /*
  要通过隐式函数实现，以implicit开头的函数就是隐式函数，以implicit开头的类就是隐式类

  我们通过隐式函数自动给已知的对象新增功能
  规则：
  1、要求隐式函数必须在对象调用的可见范围（作用域）
  2、当前的对象会自动的到作用域内查找可用的隐式函数，找到后自动匹配
  3、要让当前对象对应的类型作为隐式函数的参数
   */
  implicit def int2Byte(x: Int): Byte = x.toByte
}

/**
 * 隐式类
 */
import RichFile._
object Scala_05_implicit_02 {

  def main(args: Array[String]): Unit = {
    // 需求：通过File读取文档，得到内容后转成字符串，我们希望通过隐式类对已有类的功能进行扩展
    val source = new File("file/0419/a.txt").read
    println(source)
  }

  // 定义隐式类：将File自动转化成RichFile--隐式转换
  /*
  1、类必须有implicit修饰
  2、隐式类的参数必须是原始类（File）
  3、一定要让隐式类在原始类的作用域内
   */
  //改进前写法，隐式类在主类中，比较累赘
  //  implicit class RichFile(file: File) {
  //    val read: String = {
  //      val source = Source.fromFile(file.getPath)
  //      val result = source.getLines().mkString("\n")
  //      source.close()
  //      result
  //    }
  //  }
}

/*
改进方法：
  1、通过生成一对儿伴生类和伴生对象实现
  2、将read方法放在伴生类中
  3、将File对应的隐式方法放在伴生对象中
 */
// 伴生类
class RichFile(file: File) {
  val read: String = {
          val source = Source.fromFile(file.getPath)
          val result = source.getLines().mkString("\n")
          source.close()
          result
        }
}
// 伴生对象
object RichFile {
  // 隐式方法
  implicit def file2RichFile(file: File): RichFile = new RichFile(file)
}

/**
 * 隐式参数
 */
object Scala_06_implicit_03 {
  def main(args: Array[String]): Unit = {
    implicit val a: add = (x: Int, y: Int) => x + y
    println(addTest(1, 2))
  }

  trait add { def add(x: Int, y: Int): Int }
  def addTest(x: Int, y: Int)(implicit add: add)= add.add(x, y)
}